package com.accelstack.cmp.service;

import com.accelstack.cmp.dto.ServerWithComponentsRequest;
import com.accelstack.cmp.entity.*;
import com.accelstack.cmp.enums.HostStatus;
import com.accelstack.cmp.enums.PlatformType;
import com.accelstack.cmp.enums.ServerStatus;
import com.accelstack.cmp.enums.VirtualGpuStatus;
import com.accelstack.cmp.enums.VirtualGpuType;
import com.accelstack.cmp.repository.ServerRepository;
import com.accelstack.cmp.repository.VirtualGpuRepository;
import com.accelstack.cmp.repository.VirtualizationHostRepository;
import com.accelstack.cmp.repository.VirtualizationPlatformRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务器Service
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ServerService {
    
    private final ServerRepository serverRepository;
    private final VirtualizationHostRepository virtualizationHostRepository;
    private final VirtualizationPlatformRepository virtualizationPlatformRepository;
    private final VirtualGpuRepository virtualGpuRepository;
    
    @Transactional
    public Server create(Server server) {
        return serverRepository.save(server);
    }
    
    /**
     * 创建服务器（包含硬件组件）
     * 通过级联保存，一次性创建服务器及其所有硬件组件
     */
    @Transactional
    public Server createWithComponents(ServerWithComponentsRequest request) {
        Server server = request.getServer();
        server.setCreatedAt(new Date());
        
        // 添加CPU
        if (request.getCpus() != null) {
            for (Cpu cpu : request.getCpus()) {
                server.addCpu(cpu);
            }
        }
        
        // 添加内存
        if (request.getMemories() != null) {
            for (Memory memory : request.getMemories()) {
                server.addMemory(memory);
            }
        }
        
        // 添加磁盘
        if (request.getDisks() != null) {
            for (Disk disk : request.getDisks()) {
                server.addDisk(disk);
            }
        }
        
        // 添加网卡
        if (request.getNetworkInterfaces() != null) {
            for (NetworkInterface nic : request.getNetworkInterfaces()) {
                server.addNetworkInterface(nic);
            }
        }
        
        // 添加物理GPU
        if (request.getPhysicalGpus() != null) {
            for (PhysicalGpu gpu : request.getPhysicalGpus()) {
                server.addPhysicalGpu(gpu);
            }
        }
        
        // 由于配置了cascade = CascadeType.ALL，保存server时会级联保存所有硬件组件
        Server savedServer = serverRepository.save(server);
        
        // 自动创建虚拟化主机和虚拟GPU
        createVirtualizationHostAndVgpus(savedServer);
        
        return savedServer;
    }
    
    /**
     * 创建虚拟化主机和虚拟GPU
     */
    private void createVirtualizationHostAndVgpus(Server server) {
        // 1. 获取或创建OpenStack虚拟化平台
        VirtualizationPlatform platform = getOrCreateOpenstackPlatform();
        
        // 2. 创建虚拟化主机
        VirtualizationHost virtHost = new VirtualizationHost();
        virtHost.setServer(server);
        virtHost.setVirtPlatform(platform);
        virtHost.setName(server.getHostname() + "-virt");
        virtHost.setStatus(HostStatus.ACTIVE);
        
        // 计算资源
        int totalCpuCores = server.getCpus().stream()
                .mapToInt(cpu -> cpu.getCores() != null ? cpu.getCores() : 0)
                .sum();
        int totalMemoryGb = server.getMemories().stream()
                .mapToInt(mem -> mem.getCapacityGb() != null ? mem.getCapacityGb() : 0)
                .sum();
        int totalDiskGb = server.getDisks().stream()
                .mapToInt(disk -> disk.getCapacityGb() != null ? disk.getCapacityGb() : 0)
                .sum();
        
        virtHost.setTotalVcpus(totalCpuCores);
        virtHost.setTotalMemoryGb(totalMemoryGb);
        virtHost.setTotalDiskGb(totalDiskGb);
        virtHost.setUsedVcpus(0);
        virtHost.setUsedMemoryGb(0);
        virtHost.setUsedDiskGb(0);
        
        // GPU资源
        int physicalGpuCount = server.getPhysicalGpus().size();
        virtHost.setTotalPhysicalGpus(physicalGpuCount);
        virtHost.setTotalVirtualGpus(0);
        virtHost.setUsedVirtualGpus(0);
        virtHost.setAvailableVirtualGpus(0);
        
        VirtualizationHost savedVirtHost = virtualizationHostRepository.save(virtHost);
        
        log.info("已为服务器 {} 创建虚拟化主机，ID: {}", server.getHostname(), savedVirtHost.getId());
        
        // 3. 为每个物理GPU创建虚拟GPU（直通模式）
        int vgpuCount = 0;
        for (PhysicalGpu physicalGpu : server.getPhysicalGpus()) {
            VirtualGpu vgpu = new VirtualGpu();
            vgpu.setVirtHost(savedVirtHost);
            vgpu.setPhysicalGpu(physicalGpu);
            vgpu.setName(server.getHostname() + "-vgpu-" + vgpuCount);
            vgpu.setType(VirtualGpuType.PASSTHROUGH);
            vgpu.setStatus(VirtualGpuStatus.AVAILABLE);
            
            // 设置虚拟GPU显存（与物理GPU相同）
            if (physicalGpu.getGpuModel() != null && physicalGpu.getGpuModel().getVramGb() != null) {
                vgpu.setMemoryMb(physicalGpu.getGpuModel().getVramGb() * 1024);
            }
            
            vgpu.setDescription("基于物理GPU的直通虚拟GPU");
            vgpu.setCreatedAt(new Date());
            
            virtualGpuRepository.save(vgpu);
            vgpuCount++;
        }
        
        // 更新虚拟化主机的虚拟GPU统计
        if (vgpuCount > 0) {
            savedVirtHost.setTotalVirtualGpus(vgpuCount);
            savedVirtHost.setAvailableVirtualGpus(vgpuCount);
            virtualizationHostRepository.save(savedVirtHost);
            
            log.info("已为虚拟化主机 {} 创建 {} 个虚拟GPU（直通模式）", savedVirtHost.getName(), vgpuCount);
        }
    }
    
    /**
     * 获取或创建OpenStack虚拟化平台
     */
    private VirtualizationPlatform getOrCreateOpenstackPlatform() {
        List<VirtualizationPlatform> platforms = virtualizationPlatformRepository.findAll();
        
        // 查找是否已存在OpenStack平台
        Optional<VirtualizationPlatform> existingPlatform = platforms.stream()
                .filter(p -> p.getType() == PlatformType.OPENSTACK)
                .findFirst();
        
        if (existingPlatform.isPresent()) {
            return existingPlatform.get();
        }
        
        // 创建新的OpenStack平台
        VirtualizationPlatform platform = new VirtualizationPlatform();
        platform.setName("OpenStack Platform");
        platform.setType(PlatformType.OPENSTACK);
        platform.setDescription("自动创建的OpenStack虚拟化平台");
        platform.setCreatedAt(new Date());
        
        VirtualizationPlatform saved = virtualizationPlatformRepository.save(platform);
        log.info("已创建OpenStack虚拟化平台，ID: {}", saved.getId());
        
        return saved;
    }
    
    @Transactional
    public Server update(Server server) {
        return serverRepository.save(server);
    }
    
    @Transactional
    public void deleteById(Long id) {
        serverRepository.deleteById(id);
    }
    
    public Optional<Server> findById(Long id) {
        return serverRepository.findById(id);
    }
    
    public Server findByIdWithRelations(Long id) {
        return serverRepository.findByIdWithRelations(id);
    }
    
    public List<Server> findAll() {
        return serverRepository.findAll();
    }
    
    public Page<Server> findAll(Pageable pageable) {
        return serverRepository.findAll(pageable);
    }
    
    public List<Server> findByDatacenterId(Long datacenterId) {
        return serverRepository.findByDatacenterId(datacenterId);
    }
    
    public List<Server> findByStatus(ServerStatus status) {
        return serverRepository.findByStatus(status);
    }
    
    public List<Server> findByRackId(Long rackId) {
        return serverRepository.findByRackId(rackId);
    }
    
    /**
     * 批量创建服务器
     */
    @Transactional
    public List<Server> batchCreate(List<Server> servers) {
        return serverRepository.saveAll(servers);
    }
    
    /**
     * 批量删除服务器
     */
    @Transactional
    public void batchDelete(List<Long> ids) {
        serverRepository.deleteAllById(ids);
    }
    
    /**
     * 批量更新服务器状态
     */
    @Transactional
    public void batchUpdateStatus(List<Long> ids, ServerStatus status) {
        List<Server> servers = serverRepository.findAllById(ids);
        servers.forEach(server -> {
            server.setStatus(status);
            server.setUpdatedAt(new Date());
        });
        serverRepository.saveAll(servers);
    }
    
    /**
     * 搜索服务器（根据主机名或管理IP）
     */
    public List<Server> searchByKeyword(String keyword) {
        List<Server> allServers = serverRepository.findAll();
        return allServers.stream()
                .filter(server -> 
                    (server.getHostname() != null && server.getHostname().toLowerCase().contains(keyword.toLowerCase())) ||
                    (server.getManagementIp() != null && server.getManagementIp().contains(keyword)) ||
                    (server.getSerialNumber() != null && server.getSerialNumber().toLowerCase().contains(keyword.toLowerCase()))
                )
                .collect(Collectors.toList());
    }
    
    /**
     * 获取服务器统计信息
     */
    public Map<String, Object> getStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 总数
        long totalCount = serverRepository.count();
        statistics.put("totalCount", totalCount);
        
        // 按状态统计
        List<Server> allServers = serverRepository.findAll();
        Map<ServerStatus, Long> statusStats = allServers.stream()
                .filter(server -> server.getStatus() != null)
                .collect(Collectors.groupingBy(Server::getStatus, Collectors.counting()));
        statistics.put("statusStatistics", statusStats);
        
        // 按数据中心统计
        Map<String, Long> datacenterStats = allServers.stream()
                .filter(server -> server.getDatacenter() != null)
                .collect(Collectors.groupingBy(
                    server -> server.getDatacenter().getName(),
                    Collectors.counting()
                ));
        statistics.put("datacenterStatistics", datacenterStats);
        
        // 按机架统计（有机架分配的服务器数量）
        long serversWithRack = allServers.stream()
                .filter(server -> server.getRack() != null)
                .count();
        long serversWithoutRack = totalCount - serversWithRack;
        Map<String, Long> rackStats = new HashMap<>();
        rackStats.put("withRack", serversWithRack);
        rackStats.put("withoutRack", serversWithoutRack);
        statistics.put("rackAllocation", rackStats);
        
        return statistics;
    }
}

